﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Kpmg.Web
{
    /// <summary>
    /// Summary description for KpmgRepeater
    /// </summary>
    public class KpmgRepeater
    {
        private Repeater _repeater { get; set; }
        public string Name { get; private set; }
        public string Title { get; private set; }
        public int Width { get; private set; }
        public HiddenField SortKey { get; set; }

        public IList<KpmgRepeaterColumn> Columns { get; set; }
        public IList<KpmgRepeaterRow> Rows { get; set; }

        public KpmgRepeater(string name, int width, IList<KpmgRepeaterColumn> columns, IList<KpmgRepeaterRow> rows)
        {
            this.Name = name;
            this.Title = name;
            this.Width = width;
            this.Columns = columns;
            this.Rows = rows;
        }

        public KpmgRepeater(string name, int width, HiddenField sortKey, IList<KpmgRepeaterColumn> columns, IList<KpmgRepeaterRow> rows)
        {
            this.Name = name;
            this.Title = name;
            this.Width = width;
            this.Columns = columns;
            this.Rows = rows;
            this.SortKey = sortKey;
        }

        public KpmgRepeater(string name, string title, int width, HiddenField sortKey, IList<KpmgRepeaterColumn> columns, IList<KpmgRepeaterRow> rows)
        {
            this.Name = name;
            this.Title = title;
            this.Width = width;
            this.Columns = columns;
            this.Rows = rows;
            this.SortKey = sortKey;
        }

        public void Create(Repeater rpt)
        {
            this._repeater = rpt;
            rpt.HeaderTemplate = new KpmgRepeaterHeader(this);
            rpt.FooterTemplate = new KpmgRepeaterFooter(this);
            rpt.ItemTemplate = new KpmgRepeaterItem(this);
            rpt.ItemCommand += ItemCommand;
            Sort();
            rpt.DataSource = this.Rows;
            rpt.DataBind();
        }

        private void Sort()
        {
            if (this.SortKey != null && String.IsNullOrEmpty(this.SortKey.Value))
            {
                var col = this.Columns.FirstOrDefault(x => x.Sortable != Sortable.None);
                if (col != null)
                {
                    string[] strSk = col.Sortable.ToString().Split(new string[] { "_" }, StringSplitOptions.RemoveEmptyEntries);
                    this.SortKey.Value = col.Code + "," + strSk[1];
                }
            }

            if (this.SortKey != null && !String.IsNullOrEmpty(this.SortKey.Value))
            {
                string[] sortKeys = this.SortKey.Value.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
                if (sortKeys[1].Equals(SortDirection.Ascending.ToString()))
                    this.Rows = this.Rows.OrderBy(x => x.Items[sortKeys[0]].SortValue).ToList();
                else
                    this.Rows = this.Rows.OrderByDescending(x => x.Items[sortKeys[0]].SortValue).ToList();
            }
        }

        protected void ItemCommand(object source, RepeaterCommandEventArgs e)
        {
            ActionType type;
            if (Enum.TryParse<ActionType>(e.CommandName, true, out type))
            {
                switch (type)
                {
                    case ActionType.Sort:
                        string sortKey = e.CommandArgument.ToString();
                        if (!String.IsNullOrEmpty(sortKey) && sortKey.Contains(","))
                        {
                            string[] sortKeys = sortKey.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
                            if (sortKeys[1].Equals(SortDirection.Ascending.ToString()))
                            {
                                //this.Rows = this.Rows.OrderBy(x => x.Items[sortKeys[0]].SortValue).ToList();
                                this.SortKey.Value = sortKeys[0] + "," + SortDirection.Ascending.ToString();
                            }
                            else
                            {
                                //this.Rows = this.Rows.OrderByDescending(x => x.Items[sortKeys[0]].SortValue).ToList();
                                this.SortKey.Value = sortKeys[0] + "," + SortDirection.Descending.ToString();
                            }
                            Create(this._repeater);
                        }
                        break;
                    default:
                        //throw new NotImplementedException();                
                        break;
                }
            }
            else
                CustomItemCommand(source, e);
        }

        public event RepeaterCommandEventHandler CustomItemCommand;

        #region ITemplate
        internal class KpmgRepeaterHeader : ITemplate
        {
            private KpmgRepeater krpt { get; set; }

            public KpmgRepeaterHeader(KpmgRepeater krpt)
            {
                this.krpt = krpt;
            }

            public void InstantiateIn(Control container)
            {
                container.Controls.Add(new LiteralControl("<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" class=\"KpmgRepeater\" >"));
                container.Controls.Add(new LiteralControl("<thead><tr>"));
                foreach (var col in this.krpt.Columns)
                {
                    container.Controls.Add(new LiteralControl("<th class='Repeater RepeaterHeader' width='" + col.Width + "'>"));
                    switch (col.Sortable)
                    {
                        #region sort1
                        case Sortable.Sort1_Ascending:
                        case Sortable.Sort1_Descending:
                            string sortDir = this.krpt.SortKey.Value.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries)[1];
                            Page pageCurrent = HttpContext.Current.Handler as Page;
                            string strImg = "<img src=\"" + pageCurrent.ResolveUrl("~/images/sort_" + sortDir + ".gif") + "\" style=\"padding-left:5px\" />";
                            if (sortDir.Equals(SortDirection.Ascending.ToString()))
                                sortDir = SortDirection.Descending.ToString();
                            else
                                sortDir = SortDirection.Ascending.ToString();
                            LinkButton lbtn = new LinkButton()
                            {
                                Text = col.Title + strImg,
                                CommandName = ActionType.Sort.ToString(),
                                CommandArgument = col.Code + "," + sortDir
                            };
                            container.Controls.Add(lbtn);
                            break;

                        #endregion

                        #region sort2
                        case Sortable.Sort2_Ascending:
                        case Sortable.Sort2_Descending:
                            ImageButton ibtn1 = new ImageButton()
                            {
                                ImageUrl = "~/Image/sort_down_v2.png",
                                CommandName = ActionType.Sort.ToString(),
                                CommandArgument = col.Code + "," + SortDirection.Ascending.ToString()
                            };
                            ImageButton ibtn2 = new ImageButton()
                            {
                                ImageUrl = "~/Image/sort_up_v2.png",
                                CommandName = ActionType.Sort.ToString(),
                                CommandArgument = col.Code + "," + SortDirection.Descending.ToString()
                            };
                            container.Controls.Add(new LiteralControl(col.Title));
                            container.Controls.Add(ibtn1);
                            container.Controls.Add(ibtn2);
                            break;
                        #endregion

                        default:
                            container.Controls.Add(new LiteralControl(col.Title));
                            break;
                    }
                    container.Controls.Add(new LiteralControl("</th>"));
                }
                container.Controls.Add(new LiteralControl("</tr></thead>"));
                container.Controls.Add(new LiteralControl("<tbody>"));
            }
        }

        internal class KpmgRepeaterItem : ITemplate
        {
            private int idx { get; set; }
            private KpmgRepeater krpt { get; set; }

            public KpmgRepeaterItem(KpmgRepeater krpt)
            {
                this.idx = 0;
                this.krpt = krpt;
            }

            public void InstantiateIn(Control container)
            {
                KpmgRepeaterRow row = krpt.Rows[(idx++ % krpt.Rows.Count)];

                container.Controls.Add(new LiteralControl("<tr>"));
                foreach (var col in krpt.Columns)
                {
                    if (idx % 2 == 1)
                        container.Controls.Add(new LiteralControl("<td class='Repeater RepeaterItem'>"));
                    else
                        container.Controls.Add(new LiteralControl("<td class='Repeater RepeaterAlternatingItem'>"));

                    if (row.Items.ContainsKey(col.Code))
                    {
                        var cell = row.Items[col.Code];

                        switch (col.ColumnType)
                        {
                            case KpmgRepeaterDataType.Text:
                                container.Controls.Add(new LiteralControl(cell.Value));
                                break;

                            case KpmgRepeaterDataType.Hyperlink:
                                break;

                            case KpmgRepeaterDataType.Button:
                                Button btn = new Button();
                                btn.Text = cell.Value;
                                btn.CssClass = "RepeaterButton";
                                //btn.CommandName = !String.IsNullOrEmpty(col.Command.CommandName) ? col.Command.CommandName :
                                //    !String.IsNullOrEmpty(cell.Command.CommandName) ? cell.Command.CommandName : String.Empty;
                                if (cell.Command != null)
                                {
                                    btn.CommandName = cell.Command.CommandName;
                                    btn.CommandArgument = DataUtil.ToJsonString(cell.Command.CommandArgument);
                                }
                                container.Controls.Add(btn);
                                break;

                            case KpmgRepeaterDataType.LinkButton:
                                LinkButton lbtn = new LinkButton();
                                lbtn.Text = cell.Value;
                                lbtn.CssClass = "RepeaterHyperlink";
                                //lbtn.CommandName = !String.IsNullOrEmpty(col.Command.CommandName) ? col.Command.CommandName :
                                //    !String.IsNullOrEmpty(cell.Command.CommandName) ? cell.Command.CommandName : String.Empty;
                                if (cell.Command != null)
                                {
                                    lbtn.CommandName = cell.Command.CommandName;
                                    lbtn.CommandArgument = DataUtil.ToJsonString(cell.Command.CommandArgument);
                                }
                                container.Controls.Add(lbtn);
                                break;
                        }
                    }
                    else
                    {
                        container.Controls.Add(new LiteralControl("&nbsp;"));
                    }
                    container.Controls.Add(new LiteralControl("</td>"));
                }
                container.Controls.Add(new LiteralControl("</tr>"));
            }
        }

        internal class KpmgRepeaterFooter : ITemplate
        {
            private KpmgRepeater krpt { get; set; }

            public KpmgRepeaterFooter(KpmgRepeater krpt)
            {
                this.krpt = krpt;
            }

            public void InstantiateIn(Control container)
            {
                int cntCol = krpt.Columns.Count();
                StringBuilder sbVal = new StringBuilder();

                container.Controls.Add(new LiteralControl("</tbody>"));
                container.Controls.Add(new LiteralControl("<tfoot>"));

                if (krpt.Rows.Count == 0)
                    sbVal.Append("<tr><td align='center' colspan='" + cntCol + "' class='Repeater RepeaterItem RepeaterFirstItem'>The list is empty</td></tr>");
                sbVal.Append("<tr>");
                sbVal.Append("<td class='RepeaterFooter' colspan='" + cntCol + "'></td>");
                sbVal.Append("</tr>");
                container.Controls.Add(new LiteralControl(sbVal.ToString()));

                container.Controls.Add(new LiteralControl("</tfoot>"));
                container.Controls.Add(new LiteralControl("</table>"));
            }
        }
        #endregion
    }

    #region Other
    public class KpmgRepeaterColumn
    {
        public string Code { get; set; }
        public string Title { get; set; }
        public int Width { get; set; }
        public Sortable Sortable { get; set; }
        public KpmgRepeaterDataType ColumnType { get; set; }
        public KpmgRepeaterCommand Command { get; set; }
    }

    public class KpmgRepeaterRow
    {
        public IDictionary<string, KpmgRepeaterCell> Items { get; set; }
    }

    public class KpmgRepeaterCell
    {
        public string DataType { get; set; }
        public string Value { get; set; }
        public string SortValue { get; set; }
        public KpmgRepeaterCommand Command { get; set; }
        public IDictionary<string, string> OtherInfo { get; set; }

        public KpmgRepeaterCell() { }

        public KpmgRepeaterCell(string value, string sortValue)
        {
            this.Value = value;
            this.SortValue = sortValue;
        }

        public KpmgRepeaterCell(string value, string sortValue, KpmgRepeaterCommand command)
        {
            this.Value = value;
            this.SortValue = sortValue;
            this.Command = command;
        }
    }

    public class KpmgRepeaterCommand
    {
        public string CommandSource { get; set; }
        public string CommandName { get; set; }
        public IDictionary<string, string> CommandArgument { get; set; }

        public KpmgRepeaterCommand() { }

        public KpmgRepeaterCommand(string commandName)
        {
            this.CommandName = commandName;
            this.CommandArgument = new Dictionary<string, string>();
        }

        public KpmgRepeaterCommand(string commandName, IDictionary<string, string> commandArgument)
        {
            this.CommandName = commandName;
            this.CommandArgument = CommandArgument;
        }

        public KpmgRepeaterCommand(string commandSource, string commandName, IDictionary<string, string> commandArgument)
        {
            this.CommandSource = commandSource;
            this.CommandName = commandName;
            this.CommandArgument = commandArgument;
        }
    }

    public enum KpmgRepeaterDataType { Text, Button, LinkButton, Hyperlink }
    public enum ActionType { None, Sort, Redirect, Export, SelectAll, SelectOne }
    public enum Sortable { None, Sort1_Ascending, Sort1_Descending, Sort2_Ascending, Sort2_Descending }
    #endregion
}